package com.zoho.daliansheng.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zoho.daliansheng.common.U8SystemRecord;
import com.zoho.daliansheng.common.ZohoRecord;
import com.zoho.daliansheng.config.CRMPathConfig;
import com.zoho.daliansheng.config.DatasourceEnum;
import com.zoho.daliansheng.config.U8SystemPathConfig;
import com.zoho.daliansheng.dlcr.DlcrU8WebService;
import com.zoho.daliansheng.dlcr.DlcrU8WebServiceSoap;
import com.zoho.daliansheng.dlcr.QueryRetInfo;
import com.zoho.daliansheng.utils.CommonUtil;
import com.zoho.daliansheng.utils.CrmApiUtil;
import com.zoho.daliansheng.utils.getCrmFieldUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AcceptDetailListServiceImpl implements AcceptDetailListService {

    ZohoRecord zohoRecord;

    U8SystemRecord u8SystemRecord;

    U8SystemPathConfig u8SystemPathConfig;

    CRMPathConfig crmPathConfig;

    public AcceptDetailListServiceImpl(ZohoRecord zohoRecord, U8SystemRecord u8SystemRecord, U8SystemPathConfig u8SystemPathConfig, CRMPathConfig crmPathConfig) {
        this.zohoRecord = zohoRecord;
        this.u8SystemRecord = u8SystemRecord;
        this.u8SystemPathConfig = u8SystemPathConfig;
        this.crmPathConfig = crmPathConfig;
    }

    @Override
    public void synAcceptDetailList() {

        /*
         * 1 获取CRM 收款单 模块数据
         */
        List<String> fieldList = getCrmFieldUtil.getAcceptListFieldList();
        List<JSONObject> crmData = CrmApiUtil.getModuleData(zohoRecord.getAccessToken(), crmPathConfig.getAcceptListModuleName(), fieldList);
        System.out.println("crmData.size() = " + crmData.size());


        // 客户
        List<String> tempFieldList = getCrmFieldUtil.getAccountFieldList();
        List<JSONObject> accountData = CrmApiUtil.getModuleData(zohoRecord.getAccessToken(), crmPathConfig.getAccountModuleName(), tempFieldList);

        // 用户
        List<JSONObject> allUserData = CrmApiUtil.getAllUserData(zohoRecord.getAccessToken());

        /*
         * 2 同步ERP 收款单
         */
        try {
        synU8Data(crmData,  DatasourceEnum.GONG_CHANG.getWebServiceUrl(),DatasourceEnum.GONG_CHANG.getAccountCode(), DatasourceEnum.GONG_CHANG.getCompanyName(), accountData, allUserData);
        synU8Data(crmData,  DatasourceEnum.SU_ZHOU.getWebServiceUrl(),DatasourceEnum.SU_ZHOU.getAccountCode(), DatasourceEnum.SU_ZHOU.getCompanyName(),accountData,allUserData);
        synU8Data(crmData,  DatasourceEnum.CHANG_ZHOU.getWebServiceUrl(),DatasourceEnum.CHANG_ZHOU.getAccountCode(), DatasourceEnum.CHANG_ZHOU.getCompanyName(),accountData,allUserData);
        synU8Data(crmData,  DatasourceEnum.DA_LIAN.getWebServiceUrl(),DatasourceEnum.DA_LIAN.getAccountCode(), DatasourceEnum.DA_LIAN.getCompanyName(),accountData,allUserData);
        synU8Data(crmData, DatasourceEnum.XIN_CAI_LIAO.getWebServiceUrl(), DatasourceEnum.XIN_CAI_LIAO.getAccountCode(), DatasourceEnum.XIN_CAI_LIAO.getCompanyName(),accountData,allUserData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void synU8Data(List<JSONObject> crmData, String webServiceUrl,String accountCode, String companyName, List<JSONObject> accountData, List<JSONObject> allUserData) throws MalformedURLException {

        log.info("同步【" + companyName + "】");

        String synModuleName = crmPathConfig.getAcceptListModuleName(); // 要同步的模块名称

        // 1 过滤CRM数据，只保留单一账套
        crmData = crmData.stream().filter(object -> Objects.nonNull(object.getString("KHCompany")) && object.getString("KHCompany").equals(companyName)).collect(Collectors.toList());

        // 2 模块最大版本号
        Map<String, String> map = CrmApiUtil.getMaxVersion(zohoRecord.getAccessToken(), synModuleName, accountCode);
        String versionCrmId = map.get("id");
        int maxVersion = Integer.parseInt(map.get("maxVersion"));

        // 3 获取ERP数据
        DlcrU8WebService webService = new DlcrU8WebService(new URL(webServiceUrl));
        DlcrU8WebServiceSoap api = webService.getDlcrU8WebServiceSoap();
        QueryRetInfo queryRetInfo = api.queryApCloseBillsByVersion(maxVersion);
        int queryMaxVersion = queryRetInfo.getMaxVersion();
        JSONArray jsonArray = JSONArray.parseArray(queryRetInfo.getJson());
        if (jsonArray.size() > 0) {
            // 4 比较数据
            List<JSONObject> insertList = new ArrayList<>();
            List<JSONObject> updateList = new ArrayList<>();
            List<String> deleteList = new ArrayList<>();
            List<JSONObject> batchCurrentStock = jsonArray.toJavaList(JSONObject.class);

            if (maxVersion == -1) {
                insertList = batchCurrentStock;
            } else {
                for (JSONObject erpData : batchCurrentStock) {

                    // sys_change_operation 该字段非常关键,记录了记录的变动类型,I=Insert、U=Update、D=Delete
                    String operation = erpData.getString("sys_change_operation");

                    String batch = erpData.getString("cVouchID"); // 批号
                    List<JSONObject> searchList = crmData.stream().filter(object -> Objects.nonNull(object.getString("Name")) && object.getString("Name").equals(batch)).collect(Collectors.toList());

                    if ("I".equals(operation)) {
                        insertList.add(erpData);
                    } else if ("U".equals(operation)) {
                        if (searchList.size() > 0) {
                            JSONObject jsonObject = searchList.get(0);
                            String crmId = jsonObject.getString("id");
                            erpData.put("crmId", crmId);
                            updateList.add(erpData);
                        }
                    } else if ("D".equals(operation)) {
                        if (searchList.size() > 0) {
                            JSONObject jsonObject = searchList.get(0);
                            String crmId = jsonObject.getString("id");
                            deleteList.add(crmId);
                        }
                    }
                }
            }

            // 5 字段映射
            List<JSONObject> crm_insertList = getCrmMappingData(insertList, companyName, accountData, allUserData);
            List<JSONObject> crm_updateList = getCrmMappingData(updateList, companyName, accountData, allUserData);
            List<JSONObject> crm_empty_updateList = getEmptyLinkList(crm_updateList);
            //System.out.println("JSONObject.toJSONString(batchWarehouse) = " + JSONObject.toJSONString(batchCurrentStock));
            System.out.println("crm_insertList.size() = " + crm_insertList.size());
            System.out.println("crm_updateList.size() = " + crm_updateList.size());
            System.out.println("deleteList.size() = " + deleteList.size());

            // 6 批量操作
            CrmApiUtil.batchInsertDataByList(zohoRecord.getAccessToken(), crm_insertList, synModuleName);

            // 修改：先把子表单置空修改一次，在将数据同步进去，修改一次
            CrmApiUtil.batchUpdateDataByList(zohoRecord.getAccessToken(), crm_empty_updateList, crmPathConfig.getAcceptListModuleName());// 子表单先置空
            CrmApiUtil.batchUpdateDataByList(zohoRecord.getAccessToken(), crm_updateList, crmPathConfig.getAcceptListModuleName()); // 在更新子表单

            if (deleteList.size() > 0) {
                CrmApiUtil.batchDeleteModelData(zohoRecord.getAccessToken(), synModuleName, deleteList);
            }

            // 7 最大版本号回传
            if (queryMaxVersion != maxVersion) {
                CrmApiUtil.saveMaxVersion(zohoRecord.getAccessToken(), versionCrmId, queryMaxVersion, crmPathConfig.getMaxVersionModuleName());
            }
        }
    }

    // 获取子表单为空的数据
    private List<JSONObject> getEmptyLinkList(List<JSONObject> crm_updateList) {
        String string = JSONObject.toJSONString(crm_updateList);
        List<JSONObject> emptyList = JSONArray.parseArray(string, JSONObject.class);
        for (JSONObject jsonObject : emptyList) {
            jsonObject.put("LinkingModule13", new ArrayList<>());
        }
        return emptyList;
    }

    private List<JSONObject> getCrmMappingData(List<JSONObject> erpList, String companyName, List<JSONObject> accountData, List<JSONObject> allUserData) {
        List<JSONObject> list = new ArrayList<>();

        for (JSONObject erpData : erpList) {
            JSONObject crmData = new JSONObject();
            String crmId = erpData.getString("crmId");
            if (StringUtils.isNotBlank(crmId)) {
                crmData.put("id", crmId);
            }
            String erpCode = erpData.getString("cVouchID");

            // 因为明细数据和主表数据是混在一起的，先查下这个数据添加过没，没添加过，则添加
            List<JSONObject> addErpData = list.stream().filter(object -> object.getString("ERP").equals(erpCode)).collect(Collectors.toList());
            if (addErpData.size() > 0) {
                continue;
            }

            // 收款单明细
            List<JSONObject> crmDetailList = new ArrayList<>();

            List<JSONObject> erpDetailList = erpList.stream().filter(object -> object.getString("cVouchID").equals(erpCode)).collect(Collectors.toList());

            if (erpDetailList.size() > 0) {
                for (JSONObject detailData : erpDetailList) {
                    JSONObject jsonObject = new JSONObject();

                    jsonObject.put("Payment_type", detailData.getString("cType")); // 款项类型
                    jsonObject.put("account", detailData.getString("customerabbname")); // 客户
                    jsonObject.put("department", detailData.getString("departmentname")); // 部门
                    jsonObject.put("Salesman",  detailData.getString("personname")); // 业务员
                    jsonObject.put("amount", detailData.getString("originalamount")); // 金额
                    jsonObject.put("currency_amount", detailData.getString("amount")); // 本币金额
                    jsonObject.put("subject", detailData.getString("ckm")); // 科目
                    jsonObject.put("project", detailData.getString("project")); // 项目
                    jsonObject.put("currency_balance", detailData.getString("iRAmount")); // 本币余额
                    jsonObject.put("balance", detailData.getString("iRAmount_f")); // 余额
                    crmDetailList.add(jsonObject);
                }
                crmData.put("LinkingModule13", crmDetailList); // 明细
            }

            list.add(crmData);
        }
        return list;
    }
}

